﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using NHibernate;
using NHibernate.Criterion;
using SaleLibrary.Sale;
using SaleLibrary.License;
using BrokerBase.Lib.Client;

namespace SaleLibrary.Tools
{
    public class SaleTools
    {
        public static string Parse_Hardware_Key = "9b%u";
        public const string Parse_ClientInfo_Key = "7v(z";

        public static string[] ParseSerialCode(byte[] serialCode)
        {
            string[] ary = new string[2];

            try
            {
                byte[] data2 = E2(serialCode, Parse_Hardware_Key, Parse_Hardware_Key);

                string xml = Encoding.Unicode.GetString(data2);

                TextReader reader = new StringReader(xml);

                XElement element = XElement.Load(reader);

                ary[0] = element.Element("DiskSerialNo").Value;
                ary[1] = element.Element("MacAddress").Value;
                return ary;
            }
            catch (Exception er)
            {
                throw er;
            }
            finally
            {
                //忽略错误
            }
            
        }

        public static byte[] E1(byte[] text, string key, string iv)//加密
        {
            DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();   //实例化加/解密类对象 
            descsp.Mode = CipherMode.CBC;
            byte[] bKey = Encoding.Unicode.GetBytes(key); //定义字节数组，用来存储密钥  
            byte[] bIv = Encoding.Unicode.GetBytes(iv);
            MemoryStream ms = new MemoryStream(); //实例化内存流对象
            CryptoStream cs = new CryptoStream(ms, descsp.CreateEncryptor(bKey, bIv), CryptoStreamMode.Write);
            cs.Write(text, 0, text.Length);  //向加密流中写入数据

            cs.FlushFinalBlock();

            return ms.ToArray();
            //return Convert.ToBase64String(ms.ToArray());
        }


        private static byte[] E2(byte[] text, string key, string iv)//解密
        {
            DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();   //实例化加/解密类对象  
            descsp.Mode = CipherMode.CBC;
            byte[] bKey = Encoding.Unicode.GetBytes(key); //定义字节数组，用来存储密钥  
            byte[] bIv = Encoding.Unicode.GetBytes(iv);
            MemoryStream ms = new MemoryStream(); //实例化内存流对象    
            //使用内存流实例化解密流对象     
            CryptoStream cs = new CryptoStream(ms, descsp.CreateDecryptor(bKey, bIv), CryptoStreamMode.Write);
            cs.Write(text, 0, text.Length);      //向解密流中写入数据   
            cs.FlushFinalBlock();               //释放解密流    

            return ms.ToArray();
        }

        public static string FS(string text)
        {
            MD5 m = new MD5CryptoServiceProvider();

            byte[] data = Encoding.Unicode.GetBytes(text);

            byte[] r = m.ComputeHash(data);

            string tmp = BitConverter.ToString(r);
            tmp = tmp.Replace("-", string.Empty);
            
            return tmp;
        }

        /// <summary>
        /// 验证用户的合法性
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="terminalInfoData"></param>
        /// <param name="sess"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static bool VerifyLicense(RegistrantInfo registrantInfo, TerminalInfo terminalInfo, ISession sess, out string message)
        {
            try
            {
                message = string.Empty;

                IClient client = sess.CreateCriteria<Client>().Add(Restrictions.Eq("Name", registrantInfo.UserName)).UniqueResult<IClient>();

                //string hql = "select reg from Client c,ActiveCode code,ActiveCodeReg reg where code.Registrant.Id=c.Id and reg.ActiveCode.Id=code.Id and c.Name='" + registrantInfo.UserName + "' and (reg.DISKSerialNo='" + terminalInfo.DISKSerialNo + "' or reg.MACSerialNo='" + terminalInfo.MACSerialNo + "' or reg.MBSerialNo='"+ terminalInfo.MBSerialNo +"')";

                string hql = "select reg from Client c, ActiveCode code,ActiveCodeReg reg where code.Registrant.Id=c.Id and reg.ActiveCode.Id=code.Id and c.Name = :name and (reg.DISKSerialNo = :diskSerialNo or reg.MACSerialNo =:macSerialNo or reg.MBSerialNo =:mbSerialNo)";

                IQuery query= sess.CreateQuery(hql);

                query.SetString("name",registrantInfo.UserName);
                query.SetString("diskSerialNo", terminalInfo.DISKSerialNo);
                query.SetString("macSerialNo", terminalInfo.MACSerialNo);
                query.SetString("mbSerialNo", terminalInfo.MBSerialNo);

                IList<ActiveCodeReg> regs = query.List<ActiveCodeReg>();

                if (regs.Count > 0)
                {
                    return true;
                }else
                {
                    return false;
                }
            }
            catch (Exception er)
            {
                message = er.Message;
                return false;
            }
        }

        //public static string CalcFingerprint(string userName, string licenseCode, string code, DateTime? beginTime, DateTime? endTime, int period, string serialNo)
        //{
        //    string tmp1 = "m" + userName +"k"+licenseCode+"g"+  code + "x" + beginTime.Value.ToString("yyyy-MM-dd") + "y" + endTime.Value.ToString("yyyy-MM-dd") + "z" + period + "f" + serialNo;
            
        //    return SaleTools.FS(tmp1);
        //}

        /// <summary>
        /// 
        /// 暂时不用
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static ClientInfo ParseClientInfo(byte[] data)
        {
            ClientInfo info = new ClientInfo();

            try
            {
                byte[] tmp = E2(data, Parse_ClientInfo_Key, Parse_ClientInfo_Key);
                string text = Encoding.Unicode.GetString(tmp);

                StringReader sr = new StringReader(text);

                XElement xml= XElement.Load(sr);

                info.UserName = xml.Element("UserName").Value;
                info.PresenterName = xml.Element("PresenterName").Value;
                info.LicenseCode = xml.Element("LicenseCode").Value;
                info.DiskNo = xml.Element("DiskNo").Value;
                info.MacNo = xml.Element("MacNo").Value;

                return info;
            }
            catch 
            {
                return null;
            }
        }
    }
}
